
/*
 *
 * Copyright (C) 2009 Mattias Blomqvist, patr-blo at dsv dot su dot se
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */

using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.IO;
using System.Text;
using ClientExample.Containers;
using ClientExample.Managers;
using FlowLib.Containers;
using FlowLib.Utils.FileLists;

namespace ClientExample
{
    static class Program
    {
        public static AppSetting Settings = null;
        public static PathSetting Paths = null;
        public static ImageManager Images = new ImageManager();
        public static NotificationManager Notification = new NotificationManager();
        public static ShareManager Shares = new ShareManager();
        public static TransferManager Transfers = new TransferManager();
        static Timer timer = new Timer();
        static bool wantSaving = false;
        static DateTime lastSaved = DateTime.MinValue;

        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

            //Client.Interface.NotificationWindow notify = new ClientExample.Client.Interface.NotificationWindow();
            //notify.ShowDialog();
            //UPnPTester test = new UPnPTester();


            timer.Interval = 5 * 60 * 1000; // 5 mins
            timer.Tick += new EventHandler(timer_Tick);

            bool hasSettings = true;
            try
            {
                Settings = null;
                Paths = null;
                Load();
            }
            catch { }
            finally
            {
                if (Settings == null)
                {
                    Settings = new AppSetting();
                    hasSettings = false;					
                }
            }			
			
            bool cont = false;
            #region Guide
            if (!hasSettings || !Settings.Installed)
            {
                Guide.GuideWindow guide = new ClientExample.Guide.GuideWindow();
                cont = (guide.ShowDialog() == DialogResult.Yes);
            }
            #endregion
            #region Update Xmpl
            // TODO : Handle updates
            #endregion
            #region Run Xmpl
            if (Settings.Installed && (cont || hasSettings))
            {
                Settings.SettingsUpdated += new FlowLib.Events.FmdcEventHandler(Settings_SettingsUpdated);
				Client.Interface.MainWindow main = new Client.Interface.MainWindow();
                Application.Run(main);
                //Application.Run(new Client.Interface.MainWindow());
            }
            //else if (!Settings.Installed)
            //    MessageBox.Show("Somehow you have not installed this app properly. Please contact dev and tell him what steps you have chosen.");
            #endregion
        }

        static void timer_Tick(object sender, EventArgs e)
        {
            if (wantSaving)
            {
                Save();
                wantSaving = false;
                timer.Stop();
            }
        }

        static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            System.Exception exception = e.ExceptionObject as System.Exception;
            ShowError(exception);
        }

        static void ButtonClose_Click(object sender, EventArgs e)
        {
            Button btn = sender as Button;
            if (btn != null)
            {
                Control control = btn;
                do{
                    control = control.Parent;
                }while(!(control is Form));

                if (control is Form)
                {
                    Form form1 = control as Form;
                    if (form1 != null)
                    {
                        form1.Close();
                    }
                }
            }
        }

        static void Settings_SettingsUpdated(object sender, FlowLib.Events.FmdcEventArgs e)
        {
            Save();
        }

        public static void Save()
        {
            Save(false);
        }

        public static void Save(bool force)
        {
            try
            {
                if (!Settings.Uninstall)
                {
                    if (!force && (lastSaved != null && lastSaved.AddMinutes(5) > DateTime.Now))
                    {
                        if (!wantSaving)
                        {
                            wantSaving = true;
                            timer.Start();  // Wait 10 min to save
                        }
                        return;
                    }

                    // Don't write settings if we already doing that or reading
                    if (Settings.IsWriting || Settings.IsReading)
                    {
                        return; // It shouldn't be possible for this to happen.
                    }
                    Settings.IsWriting = true;
                    if (Paths.HaveUnSavedInfo)
                    {
                        try
                        {
                            FlowLib.Utils.FileOperations<PathSetting>.SaveObject(PathSetting.PathSettings, Paths);
                        }
                        catch { }
                    }

                    if (Settings.HaveUnSavedInfo)
                    {
                        // Settings
                        FlowLib.Utils.FileOperations<AppSetting>.SaveObject(Paths.Settings + "AppSetting.xml", Settings);
                        // Hubs
                        FlowLib.Utils.Convert.Settings.Xmpl savedHubs = new FlowLib.Utils.Convert.Settings.Xmpl();
                        savedHubs.Hubs = Settings.SavedHubs;
                        System.IO.File.WriteAllBytes(Settings.HubPath, savedHubs.Write());
                        // Friends
                        ClientExample.Utils.FriendsXml savedFriends = new ClientExample.Utils.FriendsXml();
                        savedFriends.Items = Settings.SavedFriends;
                        System.IO.File.WriteAllBytes(Settings.FriendsPath, savedFriends.Write());
                        savedFriends = null;
                        // Shares
                        Shares.Save(Settings.SharesPath);

                        Settings.HaveUnSavedInfo = false;
                        lastSaved = DateTime.Now;
                    }
                }
            }
            catch (Exception e)
            {
                ShowError(e);
            }
            finally
            {
                Settings.IsWriting = false;
            }
        }

        public static void Load()
        {
            try
            {
                if (Paths == null)
                {
                    if (System.IO.File.Exists(PathSetting.PathSettings))
                    {
                        Paths = FlowLib.Utils.FileOperations<PathSetting>.LoadObject(PathSetting.PathSettings);
                    }
                    if (Paths == null)
                    {
                        Paths = new PathSetting();
                    }
                }

                // Don't load new settings if we are currently writing from it.
                if (Settings != null && Settings.IsWriting)
                    return;

                if (System.IO.File.Exists(Paths.Settings + "AppSetting.xml"))
                {
                    Settings = FlowLib.Utils.FileOperations<AppSetting>.LoadObject(Paths.Settings + "AppSetting.xml");
                }

                // Is settings still null?
                if (Settings == null)
                {
                    Settings = new AppSetting();
                }

                // Hubs
                if (FlowLib.Utils.FileOperations.PathExists(Settings.HubPath))
                {
                    FlowLib.Utils.Convert.Settings.Xmpl savedHubs = new FlowLib.Utils.Convert.Settings.Xmpl();
                    savedHubs.Read(System.IO.File.ReadAllBytes(Settings.HubPath));
                    Settings.SavedHubs = savedHubs.Hubs;
                }
                // Friends
                if (FlowLib.Utils.FileOperations.PathExists(Settings.FriendsPath))
                {
                    ClientExample.Utils.FriendsXml savedFriends = new ClientExample.Utils.FriendsXml();
                    savedFriends.Read(System.IO.File.ReadAllBytes(Settings.FriendsPath));
                    Settings.SavedFriends = new FlowLib.Containers.FlowSortedList<Friend>(savedFriends.Items);
                    savedFriends = null;
                }
                // Shares
                if (FlowLib.Utils.FileOperations.PathExists(Settings.SharesPath + Shares.FileName + ".xml"))
                {
                    Shares.Load(Settings.SharesPath);
                }
                // Transfers
                Transfers.Load();
            }
            catch (Exception e)
            {
                ShowError(e);
            }
            finally
            {
                Settings.IsReading = false;
            }
        }

        public static void Uninstall()
        {
            Settings.Uninstall = true;
            try
            {
                System.IO.File.Delete(Settings.HubPath);
            }
            finally { }
            try
            {
                System.IO.File.Delete(PathSetting.PathSettings);
            }
            finally { }
            try
            {
                System.IO.File.Delete(Settings.FriendsPath);
            }
            finally { }
            try
            {
                System.IO.File.Delete(Settings.FriendsPath);
            }
            finally { }
            try
            {
                System.IO.Directory.Delete(Paths.Settings, true);
            }
            finally { }

            /**********
             * TODO: Some work has to be done here.
             * Filelists has to be removed.
             * Creation of uninstaller in temp directory that removes all files in this folder?
             **********/
        }

        public static void ShowError(System.Exception exception)
        {
            if (exception != null)
            {
                Form form1 = new Form();
                form1.Text = "This is a temporary solution for retreiving your Error Reports.";
                Controls.ErrorPopup errorControl = new ClientExample.Controls.ErrorPopup();

                StringBuilder sb = new StringBuilder();
                sb.AppendLine("*****************************");
                sb.AppendLine(string.Format("Version: {0}", Settings.Version));
                sb.AppendLine(string.Format("Is Mono?: {0}", AppSetting.IsRunningOnMono));
                sb.AppendLine(string.Format("Is Installed?: {0}", Settings.Installed));
                sb.AppendLine(string.Format("Connection Mode: {0}", Settings.ConnectionMode));
                try
                {
                    if (!string.IsNullOrEmpty(Settings.IP))
                    {
                        string[] sections = Settings.IP.Split('.');
                        if (sections.Length == 4)
                        {
                            sb.Append("IP: ");
                            sb.Append(sections[0]);
                            sb.Append('.');
                            sb.Append(sections[1]);
                            sb.Append('.');
                            sb.Append("***");
                            sb.Append('.');
                            sb.Append("***");
                        }
                    }
                }
                catch { }
                sb.AppendLine("*****************************");
                sb.AppendLine(exception.ToString());
				
				Console.WriteLine(sb.ToString());
				
                errorControl.Text = sb.ToString();
                errorControl.ButtonClose.Click += new EventHandler(ButtonClose_Click);
                errorControl.Dock = DockStyle.Fill;
                form1.Controls.Add(errorControl);
                form1.AcceptButton = errorControl.ButtonClose;
                form1.Width = 600;
                form1.Height = 400;
				form1.ShowDialog();
            }
        }
    }
}
